#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__

#include "Acceptor.h"
#include "TcpConnection.h"
#include <vector>
#include <sys/epoll.h>
#include <memory>
#include <map>
#include <functional>
#include <sys/eventfd.h>
#include <mutex>

using std::function;
using std::map;
using std::shared_ptr;
using std::vector;
using std::mutex;
using std::lock_guard;
using std::unique_lock;

using TcpConnectionPtr = shared_ptr<TcpConnection>;
using TcpConnectionCB = function<void(const TcpConnectionPtr &)>;
using EventLoopCB = function<void()>;


class EventLoop
{
public:
    EventLoop(Acceptor &acceptor);
    ~EventLoop();
    void loop();
    void unloop();
    void setNewConnectionCB(TcpConnectionCB &&onNewConnectionCB);
    void setMessageCB(TcpConnectionCB &&onMessageCB);
    void setCloseCB(TcpConnectionCB &&onCloseCB);

    void doPendingCB();
    void addPendingCB(EventLoopCB && cb);
    int createEvtfd();
    void writeEvtFd();
    void readEvtFd();

private:
    void waitEpollFd();
    void handleNewConnection();
    void handleMessage(int fd);
    int createEpollFd();
    void addEpollReadFd(int fd);
    void delEpollReadFd(int fd);

private:
    int _epfd;
    vector<struct epoll_event> _evtList;
    bool _isLooping;
    Acceptor &_acceptor;
    map<int, shared_ptr<TcpConnection>> _connections;

    TcpConnectionCB _onNewConnectionCB;
    TcpConnectionCB _onMessageCB;
    TcpConnectionCB _onCloseCB;

    mutex _mtx;
    int _evtFd;
    vector<EventLoopCB> _pendingCB;
};

#endif